package com.gitee.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gitee.mapper.PermissionMapper;
import com.gitee.pojo.Permission;
import com.gitee.service.IPermissionService;
import com.gitee.vo.PermissionVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import org.springframework.util.AntPathMatcher;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permission> implements IPermissionService {

    private static final Integer ROOT_PARENT_ID = 0;

    @Autowired
    private PermissionMapper permissionMapper;

    private final AntPathMatcher antPathMatcher = new AntPathMatcher();

    @Override
    public Boolean hasPermission(HttpServletRequest request, Authentication authentication) {
        Object principal = authentication.getPrincipal();
        boolean flag = false;
        if (principal instanceof UserDetails) {
            String username = ((UserDetails) principal).getUsername();
            //读取用户所拥有的权限的URL
            List<Permission> permissions = permissionMapper.selectByUsername(username);
            Set<String> urls = permissions.stream()
                    .map(Permission::getUrl)
                    .filter(url -> !StrUtil.isBlank(url)).collect(Collectors.toSet());
            for (String url : urls) {
                String URI = request.getRequestURI();
                if (antPathMatcher.match(url, URI)) {
                    flag = true;
                    break;
                }
            }
        }
        return flag;
    }

    @Override
    public List<PermissionVo> getMenuByUsername(String username) {
        List<Permission> permissions = permissionMapper.selectByUsername(username);
        //先找到一级菜单
        List<PermissionVo> permissionVos = permissions.stream()
                .filter(permission -> permission.getPid().equals(ROOT_PARENT_ID))
                .map(this::permission2PermissionVo)
                .sorted(Comparator.comparing(PermissionVo::getSort))
                .collect(Collectors.toList());
        //查询子菜单
        findSubPermissionVo(permissionVos, permissions);
        return permissionVos;
    }

    @Override
    public List<PermissionVo> getMenuTree() {
        List<Permission> permissions = super.list();
        //先找到一级菜单
        List<PermissionVo> permissionVos = permissions.stream()
                .filter(permission -> permission.getPid().equals(ROOT_PARENT_ID))
                .map(this::permission2PermissionVo)
                .sorted(Comparator.comparing(PermissionVo::getSort))
                .collect(Collectors.toList());
        //查询子菜单
        findSubPermissionVo(permissionVos, permissions);
        return permissionVos;
    }

    private void findSubPermissionVo(List<PermissionVo> permissionVos, List<Permission> permissions) {
        for (PermissionVo permissionVo : permissionVos) {
            List<PermissionVo> subPermissionVos = new ArrayList<>();
            for (Permission permission : permissions) {
                if (permissionVo.getId().equals(permission.getPid())) {
                    PermissionVo subPermissionVo = permission2PermissionVo(permission);
                    subPermissionVos.add(subPermissionVo);
                }
            }
            subPermissionVos.sort(Comparator.comparing(PermissionVo::getSort));
            permissionVo.setSubPermissionVos(subPermissionVos);
            findSubPermissionVo(subPermissionVos, permissions);
        }
    }

    private PermissionVo permission2PermissionVo(Permission permission) {
        PermissionVo permissionVo = new PermissionVo();
        BeanUtils.copyProperties(permission, permissionVo);
        return permissionVo;
    }
}
